#include "gamescene.h"
#include "common.h"
#include "player.h"
#include "bullet.h"
#include "camera.h"
#include "enemy.h"
#include "bullet.h"
#include "effect.h"
#include "path.h"
#include "conf.h"
#include "sceneobject/sceneobjectbase.h"

namespace fireplane
{
	bool GameScene::_loadAllCollisionBox(){
		unsigned long fie_size;
		unsigned char* data = CCFileUtils::sharedFileUtils()->getFileData("collision/collision.out","rb",&fie_size);
		CMemoryFile* file = createMemoryReadFile(data,fie_size,"collision/collision.out",false);


		int size;
		file->read((char*)&size,sizeof(int));
		char tbuffer[0xff];
		int total = size;

		for (int i = 0;i < total;i++){
			CollisionBox* box = new CollisionBox();

			file->read((char*)&size,sizeof(int));
			file->read((char*)tbuffer,size);
			tbuffer[size] = 0;
			box->name = tbuffer;
			
			file->read((char*)&size,sizeof(int));
			file->read((char*)tbuffer,size);
			tbuffer[size] = 0;
			
			_all_collision_box[box->name] = box;

			file->read((char*)&size,sizeof(int));
			for (int i = 0;i < size;i++){
				float x;
				float y;
				file->read((char*)&x,sizeof(float));
				file->read((char*)&y,sizeof(float));

				CCPoint point = ccp(x,y);
				box->_all_points.push_back(point);
			}
		}

		delete[] data;

		return true;
	}

	bool GameScene::init()
	{
		_loadAllCollisionBox();

		_cam = new Camera();
		_cam->init();
		addChild(_cam);

		_cam->loadMap(0);
		
		Bullet::initBulletManager(_cam->getAllBulletParent());
		Enemy::initEnemyanager(_cam->getAllEnemyParent());

		_hero = new Player();
		_hero->init(ccp(200,200));
		_cam->getHeroNode()->addChild(_hero);
		_hero->autorelease();

		Effect::setAllEffectParent(_cam->getEffectNode());
		
		Path::getPath()->loadPath(0);
		Conf::getConf()->loadConf(0);

		_gametime = 0;
		_gen_enemy_delay = 0;
		_gen_enemy_num = 0;

		scheduleUpdate();

		this->setTouchEnabled(true);
		return true;
	}

	cocos2d::CCScene* GameScene::scene()
	{
		CCScene * scene = NULL;
		do 
		{
			// 'scene' is an autorelease object
			scene = CCScene::create();
			CC_BREAK_IF(! scene);

			CCNode* parentNode = Common::createScaleNode(scene);
			// 'layer' is an autorelease object
			GameScene *layer = GameScene::node();
			CC_BREAK_IF(! layer);

			// add layer as a child to scene
			parentNode->addChild(layer);
		} while (0);

		// return the scene
		return scene;
	}

	

	bool GameScene::ccTouchBegan( CCTouch *pTouch, CCEvent *pEvent )
	{
		CCPoint pos = pTouch->getLocationInView();
		pos = CCDirector::sharedDirector()->convertToGL(pos);
		_hero->beginTouch(pos);
		return true;
	}

	void GameScene::ccTouchMoved( CCTouch *pTouch, CCEvent *pEvent )
	{
		CCPoint pos = pTouch->getLocationInView();
		pos = CCDirector::sharedDirector()->convertToGL(pos);
		_hero->moveTouch(pos);
	}


	void GameScene::ccTouchEnded( CCTouch *pTouch, CCEvent *pEvent )
	{
		CCPoint pos = pTouch->getLocationInView();
		pos = CCDirector::sharedDirector()->convertToGL(pos);
		_hero->endTouch(pos);
	}

	static int _load_idx = 0;
	static const char* const _all_load_res[] = 
	{
		"bullet/normalbullet.png",
		"plane/planes.plist",
	};

	bool GameScene::loadRes( void )
	{
		int count = sizeof(_all_load_res) / sizeof(_all_load_res[0]);

		if (_load_idx == count)
		{
			CCDirector::sharedDirector()->replaceScene(GameScene::scene());
			_load_idx = 0;
			return true;
		}
		else
		{
			string fileName = _all_load_res[_load_idx];

			Common::doLoadLogic(fileName);

			_load_idx++;
			return false;
		}
	}

	void GameScene::registerWithTouchDispatcher()
	{
		CCDirector::sharedDirector()->getTouchDispatcher()->addTargetedDelegate(this,-128 + 1,true);
	}

	void GameScene::updateGameTime(float dt)
	{
		_gametime += dt;
	}

	void GameScene::_do_gen_enemy_logic(float dt)
	{
		//return;

		static bool _only_one = true;
		_gen_enemy_delay += dt;
		Enemy::EnemyType npcType = (Enemy::EnemyType)Conf::getConf()->getInt("npcType");
	
		switch(npcType){
			case Enemy::ET_npc1:
			case Enemy::ET_npc2:
			case Enemy::ET_npc4:
			case Enemy::ET_npc5:
			case Enemy::ET_npc6:
				{
					if (_gen_enemy_delay > 3.0f && _only_one)
					{
						_only_one = false;
						_gen_enemy_delay = 0;

						Enemy::CreateNormalEnemy* cmd = (Enemy::CreateNormalEnemy*)malloc(sizeof(Enemy::CreateNormalEnemy));
						cmd->_id = npcType;
						cmd->pos = ccp(320,960 -160);

						Enemy::pushCreateCmd(cmd);
					}
				}
				break;
			case Enemy::ET_npc3:
				{
					if (_gen_enemy_delay > Conf::getConf()->getFloat("npcGenDelay") &&
						 _gen_enemy_num < Conf::getConf()->getInt("npcNumber"))
					{
						_gen_enemy_delay = 0;
						_gen_enemy_num++;

						Enemy::CreateNormalEnemy* cmd = (Enemy::CreateNormalEnemy*)malloc(sizeof(Enemy::CreateNormalEnemy));
						cmd->_id = npcType;
						cmd->pos = ccp(320,960 -160);

						Enemy::pushCreateCmd(cmd);
					}
				}
				break;
			default: 
				break;
		}
	}

	void GameScene::update( float dt )
	{
		updateGameTime(dt);
		processCollision();

		_do_gen_enemy_logic(dt);

		Enemy::updateAllEnemys(dt);
		Bullet::updateAllBullets(dt);
	}

	GameScene::GameScene()
	{
		_s_GameScene = this;
	}

	GameScene::~GameScene()
	{
		Bullet::destroyBulletManager();
		_s_GameScene = NULL;
	}

	void GameScene::processBulletCollision(){
		// process player bullet 2 enemy
		list<Bullet*>& all_bullets = Bullet::getAllBullets();
		list<Enemy*>& all_enemys = Enemy::getAllEnemys();

		list<Bullet*>::iterator bit = all_bullets.begin();
		for (;bit != all_bullets.end();bit++){
			// collision 2 enemy
			Bullet* bullet = (*bit);
			if (bullet->getBulletOwner() == Bullet::BO_PLAYER){
				list<Enemy*>::iterator eit = all_enemys.begin();
				for (;eit != all_enemys.end();eit++){
					Enemy* enemy = (*eit);

					if (bullet->isCollision2Eneny(enemy)){
						bullet->onAttack();
						enemy->onAttack();
					}
				}

				// collision 2 sceneobject
				list<SceneObjectBase*>& allsceneobjects = SceneObjectBase::getAllActiveSceneObject();
				list<SceneObjectBase*>::iterator itsceneobject = allsceneobjects.begin();
				for (;itsceneobject != allsceneobjects.end();itsceneobject++){
					SceneObjectBase* sceneobject = (*itsceneobject);

					CCPoint bpos = bullet->getWorldPos();
					if(sceneobject->isCollision2Something(bpos)){
						bullet->onAttack();
						sceneobject->onAttack(false);
					}
				}
			}
			else{
				if(bullet->isCollision2Player(Player::getMainPlayer())){
					bullet->onAttack();
				}
			}
		}
	}

	void GameScene::processEnemyCollision2Player()
	{
		list<Enemy*>& all_enemys = Enemy::getAllEnemys();
		list<Enemy*>::iterator eit = all_enemys.begin();
		for (;eit != all_enemys.end();eit++){
			Enemy* enemy = (*eit);
			// continue collision 2 player
			if(!enemy->isDestroy()){
				if(enemy->isCollision2Player(Player::getMainPlayer())){
					enemy->onCollision2Player();
				}
			}
		}

		list<SceneObjectBase*>& all_scene_objects = SceneObjectBase::getAllActiveSceneObject();
		list<SceneObjectBase*>::iterator sit = all_scene_objects.begin();
		for (;sit != all_scene_objects.end();sit ++){
			SceneObjectBase* scenobject = (*sit);
			if(scenobject->isActive()){
				if(scenobject->isCollision2Player(Player::getMainPlayer())){
					scenobject->onCollision2Player();
				}
			}
		}
	}

	void GameScene::processCollision()
	{
		processBulletCollision();
		processEnemyCollision2Player();
	}

	GameScene* GameScene::getGameScene()
	{
		return _s_GameScene;
	}

	CollisionBox* GameScene::getCollisionBox( string name )
	{
		map<string,CollisionBox*>::iterator it = _all_collision_box.find(name);
		if(it != _all_collision_box.end()){
			return it->second;
		}

		return NULL;
	}

	GameScene* GameScene::_s_GameScene = NULL;

}